#ifndef _CAMERA_H_
#define _CAMERA_H_

#ifdef _WIN32
#pragma once
#endif

/**
 * A Class to control the camera position and perspective for a device. 
 *
 * 26/02/2012 - Stephen Gore - Commented all the functions UML.
 *
 * 25/02/2012 - Stephen Gore - Created the class structure, implemented from 
 *                             UML to edit the cameras position, lookat and 
 *                             perspective.
 *   
 *                           - Created the header file. 
 *                           - Defined all functions. 
 *                           - Made sure all functions and parameters that need 
 *                             to be are const.     
 */

#include <d3dx9.h>
#include "game/constants.h"
#include "devicemanager.h"

class CCamera
{
public:
    // Get the instance of the container.
    static CCamera* getInstance();
   
    // Setup which device to manage the camera on.
    void setup(LPDIRECT3DDEVICE9 device);
   
    // Position vector. 
    void setPosition(const D3DXVECTOR3 &position);
    void setPosition(float x, float y, float z);

    D3DXVECTOR3 getPosition() const;
    void getPosition(float &x, float &y, float &z) const;
    
    // LookAt vector.
    void setLookAt(const D3DXVECTOR3 &lookat);
    void setLookAt(float x, float y, float z);

    D3DXVECTOR3 getLookAt() const;
    void getLookAt(float &x, float &y, float &z) const;

    // Up vector.
    void setUp(const D3DXVECTOR3 &up);
    void setUp(float x, float y, float z);

    D3DXVECTOR3 getUp() const;
    void getUp(float &x, float &y, float &z) const;

    // Field of View.
    void setFOVY(float angle);
    
    float getFOVY() const;

    // Aspect Ration.
    void setAspect(float ratio);

    float getAspect() const;

    // near plane.
    void setZNearPlane(float distance);

    float getZNearPlane() const;

    // far plane. 
    void setZFarPlane(float distance);

    float getZFarPlane() const;

    D3DXMATRIX getViewMatrix();
    D3DXMATRIX getProjectionMatrix();
    D3DXMATRIX getOrthoMatrix();

    // Construct matrices.
    void applyViewMatrix();
    void applyProjectionMatrix();
    void applyOrthographicMatrix(HWND hWnd);
    
    // Set up camera for 3d drawing
    void setup3D();

    // Set up camera for 2d drawing
    void setup2D();

private:
    // Constructor.
    CCamera();
    // Destructive.
    ~CCamera(){}

    // Look at matrix. 
    D3DXVECTOR3 m_vecPosition;
    D3DXVECTOR3 m_vecLookAt;
    D3DXVECTOR3 m_vecUp;

    // Perspective matrix. 
    float m_fFOVY;
    float m_fAspect;
    float m_fZN;
    float m_fZF;

    // Lookat and perspective matrix.
    D3DXMATRIX m_matProjection, m_matView, m_matOrtho; 

    // The device to manipulate the camera on.
    LPDIRECT3DDEVICE9 m_pDevice;
};
#endif